﻿using Microsoft.EntityFrameworkCore.Metadata.Internal;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;

namespace CommonModel.Util
{
    //转换函数
    public static class TransForm
    {
        //字符串编码
        public static string encode = "GB2312";

        #region 转换
        /// <summary>
        /// 结构体转字节数组
        /// </summary>
        /// <param name="structObj"></param>
        /// <returns></returns>
        public static byte[] StructToBytes(object structObj)
        {
            try
            {
                int size = Marshal.SizeOf(structObj);
                byte[] bytes = new byte[size];
                IntPtr structPtr = Marshal.AllocHGlobal(size);
                Marshal.StructureToPtr(structObj, structPtr, false);
                Marshal.Copy(structPtr, bytes, 0, size);
                Marshal.FreeHGlobal(structPtr);
                return bytes;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
        }

        /// <summary>
        /// 字节数组转结构体
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="type"></param>
        /// <param name="fill"></param>
        /// <returns></returns>
        public static object BytesToStuct(byte[] bytes, Type type, bool fill = false)
        {
            try
            {
                int size = Marshal.SizeOf(type);
                if (size > bytes.Length)
                {
                    if (fill)
                    {
                        bytes = bytes.AddBytes(new byte[size - bytes.Length]);
                    }
                    else
                    {
                        return null;
                    }
                }
                IntPtr structPtr = Marshal.AllocHGlobal(size);
                Marshal.Copy(bytes, 0, structPtr, size);
                object obj = Marshal.PtrToStructure(structPtr, type);
                Marshal.FreeHGlobal(structPtr);
                return obj;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
        }
        #endregion

        //读取台站转发站名-编码
        public static string GetStationCode(byte[] tmpBt)
        {
            //用户自定义编码
            string station_code = Encoding.GetEncoding("utf-8").GetString(tmpBt, 0, tmpBt.Length).ToString();
            station_code = station_code[..(station_code.IndexOf('\0') > 0 ? station_code.IndexOf('\0') : station_code.Length)].Replace("\0", " ").Replace(" ", " ").Trim();
            station_code = station_code.Replace(" ", "");
            station_code = station_code.Replace(Encoding.GetEncoding("utf-8").GetString(new byte[] { 255 }), "");
            return station_code;
        }

        /// <summary>
        /// 判断UUID
        /// 或者只包含字母（a-f）和数字，就是UUID去掉横杠
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsValidUuid(string input)
        {
            Regex regexUUID = new Regex(@"^[A-Fa-f\d]{8}-([A-Fa-f\d]{4}-){3}[A-Fa-f\d]{12}$");
            Regex regex = new Regex(@"^[a-fA-F\d]+$");
            return regexUUID.Match(input).Success || regex.Match(input).Success;
        }

        /// <summary>
        /// 替代Thread.Sleep(n)的直接执行
        /// n很小很小时更精确
        /// 最小精度：毫秒
        /// </summary>
        /// <param name="ms">毫秒</param>
        public static void Sleep(int ms)
        {
            if (ms > 20)
            {
                Thread.Sleep(ms - 20);
            }
            for (var since = DateTime.Now; (DateTime.Now - since).TotalMilliseconds < ms;)
            { 
                Thread.Sleep(TimeSpan.FromTicks(10));
            }
        }

        /// <summary>
        /// 判断当前是否当月倒数第N个星期几
        /// 默认得到当月倒数第一个周二
        /// </summary>
        /// <param name="n"></param>
        /// <param name="weekday"></param>
        /// <returns></returns>
        public static bool IsLastWeekdayOfMonth(int n = 1, DayOfWeek weekday = DayOfWeek.Tuesday)
        {
            DateTime today = DateTime.Today;
            // 如果今天不是weekday，直接返回false
            if (today.DayOfWeek != weekday)
            {
                return false;
            }

            DateTime dayMatch = GetLastWeekdayOfMonth(n, weekday);
            return today == dayMatch;
        }

        /// <summary>
        /// 当前是否倒数第N个星期几
        /// 如：
        /// n=1，weekday=Tuesday 就是求当月的倒数第一个周二
        /// n=2，weekday=Tuesday 就是求当月的倒数第二个周二
        /// </summary>
        /// <param name="weekday"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        private static DateTime GetLastWeekdayOfMonth(int n, DayOfWeek weekday)
        {
            DateTime date = DateTime.Now;

            // 获取当前月份的下个月的第一天，即月份的最后一天
            DateTime lastDayOfMonth = new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1);
            // 获取最后一个周二的日期
            int lastWeekdayOfMonth = lastDayOfMonth.Day;
            while (lastDayOfMonth.DayOfWeek != weekday)
            {
                lastDayOfMonth = lastDayOfMonth.AddDays(-1);
                lastWeekdayOfMonth = lastDayOfMonth.Day;
            }
            return new DateTime(date.Year, date.Month, lastWeekdayOfMonth).AddDays(-1 * (n - 1) * 7);
        }

        /// <summary>
        /// 日期串格式化
        /// </summary>
        /// <param name="dateTimeStr"></param>
        /// <param name="format"></param>
        /// <returns></returns>
        public static string DateTimeStrFormat(string dateTimeStr, String format = "yyyy-MM-dd HH:mm:ss.fff")
        {
            if ("".Equals(format) || format == null)
            {
                format = "yyyy-MM-dd HH:mm:ss.fff";
            }
            return string.Format("{0:" + format + "}", Convert.ToDateTime(dateTimeStr));
        }

        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static string GetTimeStamp(DateTime dateTime)
        {
            TimeSpan ts = dateTime - new DateTime(1970, 1, 1, 0, 0, 0, 0);

            //ts.Ticks    //总微秒数
            //ts.TotalMilliseconds    //总毫秒数 ts.Ticks/10000
            //ts.TotalSeconds //总秒数 正常的时间戳 ts.TotalMilliseconds/1000

            //return Convert.ToInt64(ts.TotalMilliseconds).ToString();
            return Convert.ToInt64(ts.Ticks).ToString();
        }

        public static string GetTimeStampSec(DateTime dateTime)
        {
            TimeSpan ts = dateTime - new DateTime(1970, 1, 1, 0, 0, 0, 0);

            //ts.Ticks    //总微秒数
            //ts.TotalMilliseconds    //总毫秒数 ts.Ticks/10000
            //ts.TotalSeconds //总秒数 正常的时间戳 ts.TotalMilliseconds/1000

            //return Convert.ToInt64(ts.TotalMilliseconds).ToString();
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        public static DateTime GetDateTime(string timeStamp)
        {
            //DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区
            DateTime startTime = new(1970, 1, 1, 0, 0, 0); // 当地时区
            //DateTime dt = startTime.AddMilliseconds(long.Parse(timeStamp));
            DateTime dt = startTime.AddTicks(long.Parse(timeStamp));
            return dt;
        }

        public static DateTime GetDateTimeMilli(string timeStamp)
        {
            //DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区
            DateTime startTime = new(1970, 1, 1, 0, 0, 0); // 当地时区
            //DateTime dt = startTime.AddMilliseconds(long.Parse(timeStamp));
            DateTime dt = startTime.AddSeconds(long.Parse(timeStamp));
            //DateTime dt = startTime.AddTicks(long.Parse(timeStamp));
            return dt;
        }

        public static DateTime GetDateTimeSec(string timeStamp)
        {
            //DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区
            DateTime startTime = new(1970, 1, 1, 0, 0, 0); // 当地时区
            //DateTime dt = startTime.AddMilliseconds(long.Parse(timeStamp));
            DateTime dt = startTime.AddSeconds(long.Parse(timeStamp));
            //DateTime dt = startTime.AddTicks(long.Parse(timeStamp));
            return dt;
        }

        public static DataTable ConvertDataReaderToDataTable(DbDataReader dataReader)
        {
            ///定义DataTable
            DataTable datatable = new();

            try
            {    ///动态添加表的数据列
                for (int i = 0; i < dataReader.FieldCount; i++)
                {
                    DataColumn myDataColumn = new()
                    {
                        //myDataColumn.DataType = dataReader.GetFieldType(i);
                        DataType = typeof(string)
                    };
                    Console.WriteLine(myDataColumn.DataType.Name);
                    myDataColumn.ColumnName = dataReader.GetName(i);
                    datatable.Columns.Add(myDataColumn);
                }

                ///添加表的数据
                while (dataReader.Read())
                {
                    DataRow myDataRow = datatable.NewRow();
                    for (int i = 0; i < dataReader.FieldCount; i++)
                    {
                        myDataRow[i] = dataReader[i].ToString();
                    }
                    datatable.Rows.Add(myDataRow);
                    myDataRow = null;
                }
                ///关闭数据读取器
                dataReader.Close();
                return datatable;
            }
            catch (Exception ex)
            {
                ///抛出类型转换错误
                //SystemError.CreateErrorLog(ex.Message);
                throw new Exception(ex.Message, ex);
            }
        }

        //字节转年月日时分秒：按实际取值（采用GMT+8作为时间基准），第一二字节表示年，第三字节表示月，第四字节表示日，第五字节表示小时，第六字节表示分钟，第七字节表示秒
        public static string ByteToDate(byte[] data)
        {
            byte[] y1 = data.Skip(0).Take(1).ToArray();
            byte[] y2 = data.Skip(1).Take(1).ToArray();
            byte[] yearb = new byte[2];
            Buffer.BlockCopy(y1, 0, yearb, 0, y1.Length);//这种方法仅适用于字节数组
            Buffer.BlockCopy(y2, 0, yearb, y1.Length, y2.Length);//将前面两个字节对调
            byte[] monthb= data.Skip(2).Take(1).ToArray();
            byte[] dayb= data.Skip(3).Take(1).ToArray();
            string year = HexChar2Value(ByteToHexString(yearb)).ToString();
            string month = HexChar2Value(ByteToHexString(monthb)).ToString();
            string day = HexChar2Value(ByteToHexString(dayb)).ToString();

            if (data.Length > 4)
            {
                byte[] hourb = data.Skip(4).Take(1).ToArray();
                byte[] minuteb = data.Skip(5).Take(1).ToArray();
                byte[] secondb = data.Skip(6).Take(1).ToArray();
                string hour = HexChar2Value(ByteToHexString(hourb)).ToString();
                string minute = HexChar2Value(ByteToHexString(minuteb)).ToString();
                string second = HexChar2Value(ByteToHexString(secondb)).ToString();
                return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
            }
            return year + "-" + month + "-" + day;
        }

        /// <summary>
        /// 是否int
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsInt(string value)
        {
            return value != null && !"".Equals(value) && Regex.IsMatch(value, @"^[+-]?\d*$");
        }

        /// <summary>
        /// 判断浮点类型
        /// </summary>
        /// <param name="inputData"></param>
        /// <returns></returns>
        public static bool IsDecimalSign(string inputData)
        {
            //if ("".Equals(inputData))
            //{
            //    return false;
            //}
            //Regex RegDecimalSign = new("^[+-]?[0-9]+[.]?[0-9]+$");
            //Match m = RegDecimalSign.Match(inputData);
            //return m.Success;

            float f;
            return float.TryParse(inputData, out f);
        }

        public static bool IsFloat(string inputData)
        {
            float f;
            return float.TryParse(inputData, out f);
        }

        /// <summary>
        /// 判断float是否NaN或者Infinity无穷大
        /// 返回默认值
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public static float IsNanInfinity(float num)
        {
            if (float.IsNaN(num))
            {
                num = 0;
            }
            else if (float.IsInfinity(num))
            {
                num = -1;
            }

            return num;
        }

        public static IList<char> HexSet = new List<char>() { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f' };
        public static IList<char> NumSet = new List<char>() { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
        /// <summary>
        /// 判断十六进制字符串hex是否正确
        /// </summary>
        /// <param name="hex">十六进制字符串</param>
        /// <returns>true：不正确，false：正确</returns>
        public static bool IsHex(string hex)
        {
            foreach (char item in hex)
            {
                if (!HexSet.Contains<char>(item))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 是否全部都是数字
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        public static bool IsAllNum(string numStr)
        {
            foreach (char item in numStr)
            {
                if (!NumSet.Contains<char>(item))
                    return true;
            }
            return false;
        }

        /*
         * 获取时间戳
         */
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);

            //ts.Ticks    //总微秒数
            //ts.TotalMilliseconds    //总毫秒数 ts.Ticks/10000
            //ts.TotalSeconds //总秒数 正常的时间戳 ts.TotalMilliseconds/1000

            //return Convert.ToInt64(ts.Ticks).ToString();
            return Convert.ToInt64(ts.TotalMilliseconds).ToString();
        }

        //十六进制字符串转为十进制
        public static int HexChar2Value(string a)
        {
            a = a.Replace("0x", "");
            int b = Int32.Parse(a, System.Globalization.NumberStyles.HexNumber);
            return b;
        }

        //字节转时分秒：按实际取值，第一字节表示小时，第二字节表示分钟，第三字节表秒
        public static string ByteToDateShort(byte[] data) 
        {
            byte[] hourb = data.Skip(0).Take(1).ToArray();
            byte[] minuteb = data.Skip(1).Take(1).ToArray();
            byte[] secondb = data.Skip(2).Take(1).ToArray();
            string hour = HexChar2Value(ByteToHexString(hourb)).ToString();
            string minute = HexChar2Value(ByteToHexString(minuteb)).ToString();
            string second = HexChar2Value(ByteToHexString(secondb)).ToString();
            return  hour + ":" + minute + ":" + second;
        }

        /**
        * 字节转成十六进制, 原始字节串: 高位在前, 低位在后<br>
        * 即以 BigEndian 方式读取并解析字节串<br/>
        *
        * @param data: 二进制字节串
        * @return 二进制字节串对应的十六进制字符串
        */
        public static string ByteToHexStringBigEndian(byte[] data)
        {
            Array.Reverse(data);//高低位转换
            StringBuilder stringBuilder = new();

            if (data == null || data.Length <= 0)
            {
                return null;
            }

            byte datum;
            for (int m = 0; m < data.Length; m++)
            {
                datum = data[m];
                int v = datum & 0xFF;
                string hv = Convert.ToString(v, 16);
                if (hv.Length< 2)
                {
                    stringBuilder.Append(0);
                }
                stringBuilder.Append(hv);
            }

            return stringBuilder.ToString();
        }

        /**
        * 字节转成十六进制, 原始字节串: 低位在前, 高位在后<br>
        * 即以 小端 方式读取并解析字节串<br/>
        *
        * @param data: 二进制字节串
        * @return 二进制字节串对应的十六进制字符串
        */
        public static string ByteToHexString(byte[] data)
        {
            StringBuilder stringBuilder = new();

            if (data == null || data.Length <= 0)
            {
                return null;
            }

            stringBuilder.Append("0x");
            for (int i = data.Length - 1; i >= 0; i--)
            {
                int v = data[i] & 0xFF;
                string hv = Convert.ToString(v, 16);
                if (hv.Length < 2)
                {
                    stringBuilder.Append(0);
                }
                stringBuilder.Append(hv);
            }
            return stringBuilder.ToString();
        }

        /// <summary>
        /// int转十六进制
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public static string IntToHex(int num)
        {
            string hex = num.ToString("X");
            if (hex.Length % 2 != 0)
            {
                hex = "0" + hex;
            }
            return "0x" + hex;
        }

        /// <summary>
        /// 十六进制转int
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        public static int HexToInt(string hex)
        {
            return Convert.ToInt32(hex, 16);
        }

        /*
         * byte数组转IP格式，针对特定byte数组的处理
         */
        public static string BytesToFormatIp(byte[] bytes)
        {
            string result = "";
            foreach (byte b in bytes)
            {
                result += "." + b.ToString();
            }
            result = result[1..];
            return result;
        }

        /*
         * 标准格式IP地址转byte数组 
         */
        public static byte[] FormatIpToBytes(string ipAddr)
        {
            byte[] btIp = new byte[4];
            string[] ipAddrArr = ipAddr.Split('.');
            for (int i = 0; i < (ipAddrArr.Length > 4 ? 4 : ipAddrArr.Length); i++)
            {
                if (IsInt(ipAddrArr[i]))
                {
                    byte[] bti = IntToByteArray(int.Parse(ipAddrArr[i]), true, false);
                    if (bti.Length > 0)
                    {
                        btIp[i] = bti[0];
                    }
                }
            }
            return btIp;
        }

        /// <summary>
        /// 字符串加密成MD5
        /// hash编码值
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string StrToMD5Hash(string str)
        {
            //把字符串转换成字节数组
            byte[] jmq = System.Text.Encoding.Default.GetBytes(str);

            MD5 md5 = MD5.Create();//创建MD5对象
            byte[] bt = md5.ComputeHash(jmq);  //通过字节数组转换成加密字节数组（hash编码值）
            return BitConverter.ToString(bt).Replace("-", "");
        }

        /**
         * 将byte数组转为16进制
         * isInv为true，则为由高位到低位，否则反之
         * isInv 是否倒序
         */
        public static string byteToHex(byte[] bytes, Boolean isInv = false)
        {
            string returnStr = "";
            for (int i = 0; i < bytes.Length; i++)
            {
                returnStr += bytes[(isInv ? (bytes.Length - i - 1) : i)].ToString("X2");
            }
            return returnStr;
        }

        /*
         * 将16进制转换成byte数组
         * hexString 16进制字符串
         * isInv 是否倒置输出
         */
        public static byte[] HexTobyte(string hexString, bool isInv = false)
        {
            hexString = hexString.Replace("0x", "").Replace("0X", "");
            hexString = hexString.Replace(" ", "").Replace("-", "").Replace(":", "").Replace(",", "").Replace("，", "");
            if ((hexString.Length % 2) != 0)
            {
                hexString += " ";
            }
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
            {
                returnBytes[isInv ? (returnBytes.Length - i - 1) : i] = Convert.ToByte(hexString.Substring(i * 2, 2).Trim(), 16);
            }
            return returnBytes;
        }

        //字节数组转字符串，8位，一个字节
        public static string ByteToString(byte[] bytes)
        {
            /*Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);//在使用编码方法（Encoding.GetEncoding("GB2312")）之前，对编码进行注册
            string strResult = Encoding.GetEncoding(TransForm.encode).GetString(bytes, 0, bytes.Length).ToString();*/
            string strResult = string.Empty;
            string strTemp;
            for (int i = 0; i < bytes.Length; i++)
            {
                strTemp = System.Convert.ToString(bytes[i], 2);
                strTemp = strTemp.Insert(0, new string('0', 8 - strTemp.Length));
                strResult += strTemp;
            }
            /*
             * 官方定义了XML的无效字符分为三段：<br/>
             * 0x00 - 0x08<br/>
             * 0x0b - 0x0c<br/>
             * 0x0e - 0x1f<br/>
             * 这些字符即使放在CDATA中仍然解析不了，所以最好的办法是过滤掉
             */
            strResult = Regex.Replace(strResult, "[\\x00-\\x08]", "");
            strResult = Regex.Replace(strResult, "[\\x0b-\\x0c]", "");
            strResult = Regex.Replace(strResult, "[\\x0e-\\x1f]", "");

            return strResult;
        }

        //字节数组转字符串UTF8，8位，一个字节
        public static string ByteToStringUTF8(byte[] bytes)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);//在使用编码方法（Encoding.GetEncoding("GB2312")）之前，对编码进行注册
            string strResult = Encoding.GetEncoding(TransForm.encode).GetString(bytes, 0, bytes.Length).ToString();

            /*
             * 官方定义了XML的无效字符分为三段：<br/>
             * 0x00 - 0x08<br/>
             * 0x0b - 0x0c<br/>
             * 0x0e - 0x1f<br/>
             * 这些字符即使放在CDATA中仍然解析不了，所以最好的办法是过滤掉
             */
            strResult = Regex.Replace(strResult, "[\\x00-\\x08]", "");
            strResult = Regex.Replace(strResult, "[\\x0b-\\x0c]", "");
            strResult = Regex.Replace(strResult, "[\\x0e-\\x1f]", "");
            strResult = strResult.Replace("<", "");
            strResult = strResult.Replace("?", "");
            strResult = strResult.Replace("€", "");
            return strResult;
        }


        //字节数组转成float浮点数,C#默认是小端存储。long 数据类型是64位、有符号的以二进制补码表示的整数，占8字节
        public static float ByteToFloat(byte[] bytes)
        {
            float fTemp = BitConverter.ToSingle(bytes, 0);
            return fTemp;
        }

        //字节数组转成float，大端存储  ldc 20210506
        public static float ByteToFloatBigEndian(byte[] bytes)
        {
            Array.Reverse(bytes);//翻转高低位
            float fTemp = BitConverter.ToSingle(bytes, 0);
            return fTemp;
        }

        public static string ChangeDataToD(byte[] bytes)
        {
            string result = "0.00";
            try
            {
                float num = BitConverter.ToSingle(bytes, 0);
                result = Convert.ToDecimal(num).ToString("f2");
            }
            catch (Exception) { }

            return result;
        }

        //字节数组转double ，默认小端 ldc 20210506
        public static double ByteToDouble(byte[] data)
        {
            double value = BitConverter.ToDouble(data, 0);
            return value;
        }

        //字节数组转double ，大端 ldc 20210506
        public static double ByteToDoubleBigEndian(byte[] data)
        {
            Array.Reverse(data);//翻转高低位
            double value = BitConverter.ToDouble(data, 0);
            return value;
        }

        //字节数组转32位int，小端，data是四个字节，转换与IntToByteArray配合使用
        public static int ByteToInt(byte[] data)
        {
            int value = BitConverter.ToInt32(data, 0);
            return value;
        }

        //字节转int ,大端 ldc 
        public static int ByteToIntBigEndian(byte[] data)
        {
            Array.Reverse(data);
            int value = BitConverter.ToInt32(data, 0);
            return value;
        }

        //int转字节数组，大端，ldc 20210506
        public static byte[] IntToByteBigEndian(int data)
        {
            byte[] value = BitConverter.GetBytes(data);
            Array.Reverse(value);
            return value;
        }

        //int转字节数组，默认小端，ldc 20210506
        public static byte[] IntToByte(int data)
        {
            byte[] value = BitConverter.GetBytes(data);
            return value;
        }

        /// <summary>
        /// 将int转成二进制
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static string intToBit(int n)
        {
            return Convert.ToString(n, 2);
        }

        /// <summary>
        /// 字符串反转
        /// </summary>
        /// <param name="original"></param>
        /// <returns></returns>
        public static string Reverse(string original)
        {
            char[] arr = original.ToCharArray();
            Array.Reverse(arr);
            return new string(arr);
        }

        //字节数组转long，默认小端
        public static long ByteToLong(byte[] data)
        {
            long value = BitConverter.ToInt64(data, 0);
            return value;
        }

        //字节数组转long，大端，ldc 20210506
        public static long ByteToLongBigEndian(byte[] data)
        {
            Array.Reverse(data);
            long value = BitConverter.ToInt64(data, 0);
            return value;
        }

        //long转字节数组，大端，ldc 20210506
        public static byte[] LongToByteBigEndian(long data)
        {
            byte[] value=BitConverter.GetBytes(data);
            Array.Reverse(value);
            return value;
        }

        //long转字节数组，默认小端，ldc 20210506
        public static byte[] LongToByte(long data)
        {
            byte[] value = BitConverter.GetBytes(data);
            return value;
        }

        // 字节数组转成short，小端 ldc。short数据类型是16位、有符号的以二进制补码表示的整数，占2字节
        public static short ByteToShort(byte[] data)
        {
            short value = BitConverter.ToInt16(data, 0);
            return value;
        }

         //字节数组转成short，大端 ldc
        public static short ByteToShortBigEndian(byte[] data)
        {
            Array.Reverse(data);
            short value = BitConverter.ToInt16(data, 0);
            return value;
        }

        //short转字节数组，默认小端，ldc 20210506
        public static byte[] ShortToByte(short data)
        {
            byte[] value = BitConverter.GetBytes(data);
            return value;
        }

        //short转字节数组，大端，ldc 20210506
        public static byte[] ShortToByteBigEndian(short data)
        {
            byte[] value = BitConverter.GetBytes(data);
            Array.Reverse(value);
            return value;
        }

         //byte数组转IP格式，针对特定byte数组的处理
        public static string ByteToFormatIp(byte[] bytes)
        {
            string result = "";
            foreach (byte b in bytes)
            {
                result += "." + b.ToString();
            }
            result = result[1..];
            return result;
        }

        //字节数组转8位uint，uint8 数据类型是8位、有符号的以二进制补码表示的整数，占1字节，返回二进制对应的8位整型数值
        public static int ByteToUint8(byte[] data)
        {
            int value = (data[0] & 0xFF);
            return value;
        }

        //字节数组转16位uint，数据类型是16位、有符号的以二进制补码表示的整数，占2字节，默认小端 （已调试）
        public static int ByteToUint16(byte[] data)
        {
            return (data[1] << 8 & 0xFF00 | data[0] & 0xFF);
        }

        //字节数组转16位uint，数据类型是16位、有符号的以二进制补码表示的整数，占2字节，大端
        public static int ByteToUint16BigEndian(byte[] data)
        {
            Array.Reverse(data);
            return (data[0] << 8 & 0xFF00 | data[1] & 0xFF);
        }

        //字节数组转32位uint，数据类型是32位、有符号的以二进制补码表示的整数，占2字节，大端
        public static long ByteToUint32BigEndian(byte[] data)
        {
            Array.Reverse(data);
            return BitConverter.ToUInt32(data,0);
        }

        //字节数组转32位uint，数据类型是32位、有符号的以二进制补码表示的整数，占2字节，默认小端
        public static long ByteToUint32(byte[] data)
        {
            return BitConverter.ToUInt32(data, 0);
        }

        //16字节串转成ipv4地址字符串
        public static string ByteToIp(byte[] data)
        {
            string result = "";
            foreach (byte b in data)
            {
                result += "." + b.ToString();
            }
            result = result.Substring(1);
            return result;
        }

        //4字节串转成ipv4地址字符串
        public static string FourByteToIp(byte[] data)
        {
            string result = "";
            foreach (byte b in data)
            {
                result += "." + b.ToString();
            }
            result = result.Substring(1);
            return result;
        }

        /**
         * 未实现 二进制字节串转换成 BitOP 实例
         *
         * @param data: 二进制字节串
         * @return BitOP 实例
         */
        public static double bytesToBitOp(byte[] data)
        {
            // TODO 二进制字节串转换成 BitOP 实例
            return 0.0D;
        }

        /**
         * 未实现 二进制字节串转换成 ByteOp 实例
         *
         * @param data: 二进制字节串
         * @return ByteOp 实例
         */
        public static double bytesToByteOp(byte[] data)
        {
            // TODO 二进制字节串转换成 BitOP 实例
            return 0.0D;
        }

        /**
         * 未实现  二进制字节串转换成 UShortOp 实例
         *
         * @param data: 二进制字节串
         * @return UShortOp 实例
         */
        public static double bytesToUShortOp(byte[] data)
        {
            // TODO 二进制字节串转换成 ByteOp 实例
            return 0.0D;
        }

        /**
         * 未实现  二进制字节串转换成 SingleOp 实例
         *
         * @param data: 二进制字节串
         * @return SingleOp 实例
         */
        public static double bytesToSingleOp(byte[] data)
        {
            // TODO 二进制字节串转换成 SingleOp 实例
            return 0.0D;
        }

        /**
         * 未实现  二进制字节串转换成 Schedule 实例
         *
         * @param data: 二进制字节串
         * @return Schedule 实例
         */
        public static double bytesToSchedule(byte[] data)
        {
            // TODO 二进制字节串转换成 Schedule 实例
            return 0.0D;
        }

        /**
         * 未实现  二进制字节串转换成 AutoMsgCfg 实例
         *
         * @param data: 二进制字节串
         * @return AutoMsgCfg 实例
         */
        public static double bytesToAutoMsgCfg(byte[] data)
        {
            // TODO 二进制字节串转换成 AutoMsgCfg 实例
            return 0.0D;
        }

        /**
         * 未实现  二进制字节串转换成 ContRead 实例
         *
         * @param data: 二进制字节串
         * @return ContRead 实例
         */
        public static byte[] bytesToContRead(byte[] data)
        {
            // TODO 二进制字节串转换成 ContRead 实例
            return data;
        }


        /**
         * 将byte数组转换为一个长度为8*N的byte数组，数组每个值代表bit
         *
         * @param data: 二进制字节串
         * @return 二进制字节串字节字符串
         */
        public static byte[] bytesToBitArray(byte[] data)
        {
            byte[] value = new byte[8 * data.Length];
            int j = 0;
            byte one;
            for(int m = 0; m < data.Length; m++)
            {
                one = data[m];
                for (int i = 0; i <= 7; i++)
                {
                    value[i + j * 8] = (byte)(one & 1);
                    one = (byte)(one >> 1);
                }

                j++;
            }

            return value;
        }





        /**
         * 二进制字节串转换成 Mac 实例
         *
         * @param data: 二进制字节串
         * @return Mac 实例
         */
        public static String bytesToMac(byte[] data)
        {
            StringBuilder stringBuilder = new();

            if (data == null || data.Length <= 0)
            {
                return null;
            }

            for (int i = 0; i < data.Length; i++)
            {
                int value = data[i] & 0xFF;
                String hexValue = value.ToString("X"); //十进制转成十六进制

                if (hexValue.Length< 2)
                {
                    stringBuilder.Append(0);
                }

                stringBuilder.Append(hexValue);

                if (i != 0 && i != 5)
                {
                    stringBuilder.Append(':');
                }
            }

            return stringBuilder.ToString().ToUpper();
        }

        /**
         * 未实现  二进制字节串转换成 MultipathData 实例
         *
         * @param data: 二进制字节串
         * @return MultipathData 实例
         */
        public static double bytesToMultipathData(byte[] data)
        {
            // TODO 二进制字节串转换成 MultipathData 实例
            return 0.0D;
        }

        /*
         * 读取台站转发站名-编码
         */
        public static String GetStationCode(byte[] data, int start, int end)
        {
            //用户自定义编码
            byte[] tmpBt = data.Skip(start).Take(end).ToArray();//从第三位开始，取16位
            string station_code = Encoding.GetEncoding("utf-8").GetString(tmpBt, 0, tmpBt.Length).ToString();
            station_code = station_code[..(station_code.IndexOf('\0') > 0 ? station_code.IndexOf('\0') : station_code.Length)].Replace("\0", " ").Replace(" ", " ").Trim();
            station_code = station_code.Replace(" ", "");
            return station_code;
        }

        /**
         * byte[]转int，转换与IntToByteArray配合使用
         * isZero为true，则保留空位，否则反之
         * isInv为true，则为由高位到低位，否则反之
         * bytes
         */
        public static int ByteArrayToInt(byte[] bytes, Boolean isInv, Boolean isZero)
        {
            int value = 0;
            for (int i = 0; i < bytes.Length; i++)
            {
                int shift = (isInv ? (3 - i - (isZero ? 0 : (4 - bytes.Length))) : i) * 8;
                value += (bytes[i] & 0xFF) << shift;
            }
            return value;
        }

        /*
         * int到byte[]，转换与byteArrayToInt配合使用
         * asc为true，则为由高位到低位，否则反之
         * isZero为true，则保留空位，否则反之
         * @param i
         * @param asc
         * @param isZero
         * @return
         */
        public static byte[] IntToByteArray(int i, Boolean asc, Boolean isZero)
        {
            byte[] tmpBtArr = new byte[4];
            int l = 0;
            for (int n = 0; n < 4; n++)
            {
                tmpBtArr[n] = asc ? (byte)((i >> (3 - n) * 8) & 0xFF) : (byte)((i >> n * 8) & 0xFF);
                l += isZero ? 1 : (tmpBtArr[n] == 0 ? 0 : 1);
            }
            byte[] result = new byte[l];
            if (!isZero)
            {
                if (asc)
                {
                    Buffer.BlockCopy(tmpBtArr, 4 - l, result, 0, l);
                }
                else
                {
                    Buffer.BlockCopy(tmpBtArr, 0, result, 0, l);
                }
            }
            else
            {
                result = tmpBtArr;
            }
            return result;
        }

        /**
         * 按时间日期格式返回时间字符串
         * @param format
         * @return
         */
        public static string GetFormatDatetime(String format = "yyyy-MM-dd HH:mm:ss.fff")
        {
            if ("".Equals(format) || format == null)
            {
                format = "yyyy-MM-dd HH:mm:ss.fff";
            }
            return string.Format("{0:" + format + "}", DateTime.Now);
        }

        /*
         * 日期格式化
         */
        //public static string DateTimeFormat(DateTime dt, String format = "yyyy-MM-dd HH:mm:ss.fff")
        public static string DateTimeFormat(DateTime dt, String format = "yyyy-MM-dd HH:mm:ss.fffffff")
        {
            if ("".Equals(format) || format == null)
            {
                format = "yyyy-MM-dd HH:mm:ss.fff";
            }
            return string.Format("{0:" + format + "}", dt);
        }

        /// <summary>
        /// 日期时间字符串转日期格式
        /// </summary>
        /// <param name="dtStr"></param>
        /// <returns></returns>
        public static DateTime strTodateTime(string dtStr)
        {
            DateTime dt = new();
            try
            {
                DateTimeFormatInfo dtFormat = new();
                dt = Convert.ToDateTime(dtStr, dtFormat);
            }
            catch (Exception) { }

            return dt;
        }

        /// <summary>
        /// 判断网络类型
        /// </summary>
        /// <param name="ipString"></param>
        /// <returns></returns>
        public static AddressFamily GetIpType(string ipString)
        {
            AddressFamily addressFamily = AddressFamily.InterNetwork;
            try
            {
                if (IPAddress.TryParse(ipString, out IPAddress address))
                {
                    addressFamily = address.AddressFamily;
                }
                else
                {
                    addressFamily = AddressFamily.Unknown;
                }
            }
            catch { }
            return addressFamily;
        }

        /// <summary>
        /// 判断是否IP地址
        /// </summary>
        /// <param name="ipStr"></param>
        /// <returns></returns>
        public static Boolean IsIP(string ipStr)
        {
            if ("".Equals(ipStr))
            {
                return true;
            }

            if (IPAddress.TryParse(ipStr, out _))
            {
                return Regex.IsMatch(ipStr, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
                //return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 判断ip地址是否ipv6
        /// </summary>
        /// <param name="ipString"></param>
        /// <returns></returns>
        public static bool IsIPV6(string ipString)
        {
            return GetIpType(ipString) == AddressFamily.InterNetworkV6;
        }

        /// <summary>
        /// 是否时间字符串
        /// </summary>
        /// <param name="strDate"></param>
        /// <returns></returns>
        public static Boolean IsDate(string strDate)
        {
            try
            {
                DateTime.Parse(strDate);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 广西广播电视设备通用通信协议
        /// CRC16计算函数，返回CRC16校验值
        /// </summary>
        /// <param name="bytes">需要生成校验的字节数组</param>
        /// <returns>返回CRC16校验值</returns>
        public static UInt16 CRC_16(byte[] bytes)
        {
            if (bytes == null || bytes.Length == 0)
                return 0;

            UInt16 CRC = 0xFFFF;
            int tmp;
            for (int i = 0; i < bytes.Length; i++)
            {
                CRC ^= bytes[i];
                for (int j = 0; j < 8; j++)
                {
                    tmp = CRC & 0x0001;
                    CRC = (UInt16)(CRC >> 1);
                    if (tmp > 0)
                        CRC = (UInt16)(CRC ^ 0xA001);
                }
            }
            CRC = (UInt16)(((CRC >> 8) + (CRC << 8)));
            return CRC;
        }

        /// <summary>
        /// 压缩字符串
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string Compress(string value)
        {
            try
            {
                string data = " ";
                //byte[] byteArray = Encoding.Default.GetBytes(value);
                byte[] byteArray = Encoding.UTF8.GetBytes(value);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (GZipStream sw = new GZipStream(ms, CompressionMode.Compress))
                    {
                        sw.Write(byteArray, 0, byteArray.Length);
                    }
                    data = Convert.ToBase64String(ms.ToArray());
                }
                return data;
            }
            catch //(Exception ex)
            {
                //throw ex;
                return "";
            }
        }

        /// <summary>
        /// 解压缩字符串
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string Decompress(string value)
        {
            try
            { 
                string data = "";
                byte[] bytes = Convert.FromBase64String(value); 
                using (MemoryStream msReader = new MemoryStream())
                {
                    using (MemoryStream ms = new MemoryStream(bytes))
                    {
                        using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
                        { 
                            byte[] buffer = new byte[1024]; 
                            int readLen = 0;
                            while ((readLen = zip.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                msReader.Write(buffer, 0, readLen);
                            }
                        }
                    }
                    //data = Encoding.Default.GetString(msReader.ToArray());
                    data = Encoding.UTF8.GetString(msReader.ToArray());
                }
                return data;
            }
            catch //(Exception ex)
            {
                //throw ex;
                return "";
            }
        }

        /// <summary>
        /// 得到一个对象的克隆(二进制的序列化和反序列化)--需要标记可序列化
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static object Clone(object obj)
        {
            MemoryStream memoryStream = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(memoryStream, obj);
            memoryStream.Position = 0;
            return formatter.Deserialize(memoryStream);
        }

        /// <summary>
        /// byte数组拼接，扩展方法
        /// </summary>
        /// <param name="btSource">源byte[]</param>
        /// <param name="btAppend">需要新增的byte[]</param>
        /// <returns></returns>
        public static byte[] AddBytes(this byte[] btSource, byte[] btAppend)
        {
            byte[] btNew = new byte[btSource.Length + btAppend.Length];
            Buffer.BlockCopy(btSource, 0, btNew, 0, btSource.Length);
            Buffer.BlockCopy(btAppend, 0, btNew, btSource.Length, btAppend.Length);
            return btNew;
        }

        /// <summary>
        /// 执行控制台命令
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="arguments"></param>
        /// <returns></returns>
        public static string GetConsoleInfo(string fileName, string arguments)
        {
            string consoleInfo = "";
            try
            {
                var psi = new ProcessStartInfo(fileName, arguments) { RedirectStandardOutput = true };
                var process = Process.Start(psi);
                if (process != null)
                {
                    consoleInfo = process.StandardOutput.ReadToEnd();
                    process.StandardOutput.Close();
                    process.WaitForExit();
                    process.Close();
                }
            }
            catch { }

            return consoleInfo;
        }

        /// <summary>
        /// 获取宿主计算机名
        /// 创建容器时，需要做映射(- /etc/hosts:/app/hosts)
        /// 把宿主的/etc/hosts映射到本地app目录下hosts
        /// </summary>
        /// <returns></returns>
        public static string GetHostIPOrName()
        {
            string host = GetContainerAddress();
            try
            {
                if (host == null || "".Equals(host) && File.Exists("/app/hosts"))
                {
                    string hostInfo = TransForm.GetConsoleInfo("grep", "127.0.1.1 /app/hosts");
                    host = hostInfo.Split("localhost")[0].Replace("\t"," ").Replace("\n", " ").Replace("  ", " ").Replace("  ", " ").Replace("  ", " ").Trim();
                    host = (host.Split(" ").Length > 1 ? host.Split(" ")[1] : host).Trim().Replace("127.0.0.1", "");
                }

                if (host == null || "".Equals(host))
                {
                    host = GetHostName("/app/phostname");
                }
            }
            catch { }
            return host;
        }

        /// <summary>
        /// 获取宿主计算机名
        /// 创建容器时，需要做映射(- /etc/hostname:/app/phostname)
        /// 把宿主的/etc/hostname映射到本地app目录下phostname
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string GetHostName(string path = "/etc/hostname")
        {
            string host = GetContainerAddress();
            try
            {
                if (File.Exists(path))
                { 
                    string hostInfo = TransForm.GetConsoleInfo("cat", path);
                    host = hostInfo.Replace("\t", " ").Replace("\n", " ").Replace("  ", " ").Replace("  ", " ").Replace("  ", " ").Trim();
                }
            }
            catch { }
            return host;
        }

        /// <summary>
        /// 获取环境变量
        /// </summary>
        /// <param name="environmentName"></param>
        /// <returns></returns>
        public static string GetEnvironment(string environmentName)
        {
            try
            {
                return Environment.GetEnvironmentVariable(environmentName) ?? "";
            }
            catch 
            {
                return "";
            }
        }

        /// <summary>
        /// 获取docker信息
        /// 执行docker info
        /// </summary>
        /// <returns></returns>
        public static string GetDockerInfo()
        {
            return GetConsoleInfo("docker", "info");
        }
        
        /// <summary>
        /// 获取容器IP
        /// </summary>
        /// <returns></returns>
        public static string GetContainerAddress()
        {
            return GetConsoleInfo("docker", "info  -f '{{.Swarm.NodeAddr}}'").Replace("'", "").Replace("\n", "");
        }

        /// <summary>
        /// 正则替换字符串
        /// </summary>
        /// <param name="text"></param>
        /// <param name="find"></param>
        /// <param name="replacement"></param>
        /// <param name="caseSensitive"></param>
        /// <param name="startAt"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static string ReplaceText(this string text, string find, string replacement, bool caseSensitive = false, int startAt = 0, int count = -1)
        {
            try
            {
                //Regex regex = new Regex(Regex.Escape(find), (caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase));
                //return (regex.Replace(text, replacement, count, startAt));

                return text = Regex.Replace(text, find, replacement, RegexOptions.IgnoreCase);
            }
            catch (Exception)
            {
                return (text);
            }
        }

        /// <summary>
        /// 根据频率，转换成甚高频（VHF）或者特高频（UHF）频道编码
        /// 详细查看https://www.520101.com/html/base/2017393255.html
        /// </summary>
        /// <param name="frq"></param>
        /// <returns></returns>
        public static int GetDTMBChannelNo(float frq)
        {
            int channelNoStart = -1;
            float startFrq = frq;
            if (48.5 <= frq && frq <= 72.5)
            {
                channelNoStart = 1;
                startFrq = 49.5f;
            }
            else if (76 <= frq && frq <= 92)
            {
                channelNoStart = 4;
                startFrq = 77;
            }
            else if (167 <= frq && frq <= 223)
            {
                channelNoStart = 6;
                startFrq = 168;
            }
            else if (470 <= frq && frq <= 566)
            {
                channelNoStart = 13;
                startFrq = 471;
            }
            else if (606 <= frq && frq <= 958)
            {
                channelNoStart = 25;
                startFrq = 607;
            }
            int gap = (int)((frq - startFrq) / 8);
            int channelNo = channelNoStart + gap;
            return channelNo;
        }

        //第一种方法：正则表达式
        public static bool IsChinese(string Text)
        {
            for (int i = 0; i < Text.Length; i++)
            {
                if (Regex.IsMatch(Text.ToString(), @"[\u4E00-\u9FA5]+$"))
                {
                    return true;
                }
            }
            return false;

        }
        //第二种方法：汉字的 UNICODE 编码范围
        public static bool IsChinese1(string Text)
        {
            string text = Text;
            char[] c = text.ToCharArray();
            for (int i = 0; i < c.Length; i++)
                if ((int)c[i] >= 0x4e00 && (int)c[i] <= 0x9fbb)
                    return true;

            return false;

        }
        //在 ASCII码表中，英文的范围是0-127，而汉字则是大于127
        public static bool IsChinese2(string Text)
        {
            string text = Text;
            char[] c = text.ToCharArray();
            for (int i = 0; i < text.Length; i++)
            {
                if ((int)c[i] > 127)
                {
                    return true;
                }
            }
            return false;

        }


        /// <summary>
        /// base64解码
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string FromBase64(string source)
        {
            try
            {
                byte[] data = Convert.FromBase64String(source);
                string originalString = Encoding.UTF8.GetString(data);
                return originalString;
            }
            catch { }

            //报错时（源数据不是base64报错时，返回原字符串）
            return source;
        }

        /// <summary>
        /// base64编码
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string ToBase64(string source)
        {
            byte[] data = Encoding.UTF8.GetBytes(source);
            string base64String = Convert.ToBase64String(data);
            return base64String;
        }

        /// <summary>
        /// 类转字典
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static Dictionary<string, object> SelfToDictionary(this object obj)
        {
            if (obj == null) throw new ArgumentNullException(nameof(obj));

            var dictionary = new Dictionary<string, object>();
            var properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (var prop in properties)
            {
                dictionary.Add(prop.Name, prop.GetValue(obj));
            }

            return dictionary;
        }
    }
}
